﻿namespace LowLevelGraphics
{
    /// <summary>
    /// 
    /// </summary>
    public enum KernelMode
    {
        /// <summary>
        /// 
        /// </summary>
        EXPAND, //Erweitern: der Teil des Kernes wird nicht berücksichtigt
        /// <summary>
        /// 
        /// </summary>
        FOLD,   //Umfalten: der Teil des Kernes betrachtet die Pixel auf der gegenüberliegenden Seite des Bildes.
        /// <summary>
        /// 
        /// </summary>
        CUT,    //Abschneiden: die Pixel am Rand werden nicht bearbeitet und abgeschnitten.
        /// <summary>
        /// 
        /// </summary>
        NONE
    }

    /// <summary>
    /// 
    /// </summary>
    public class ConvolutionMatrixCustom
    {
        int[,] m_aInt = null;
        int m_nFactor = 0;
        int m_nOffset = 0;

        /// <summary>
        /// Gets or sets factor
        /// </summary>
        public int Factor
        {
            get { return m_nFactor; }
            set { m_nFactor = value; }
        }
        
        /// <summary>
        /// Gets or sets offset
        /// </summary>
        public int Offset
        {
            get { return m_nOffset; }
            set { m_nOffset = value; }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="_aInt"></param>
        public ConvolutionMatrixCustom(int[,] _aInt)
        {
            m_aInt = _aInt;
        }

        /// <summary>
        /// Wenn sich das aktuell bearbeitete Pixel am Rand des Bildes befindet, ist ein Teil des Kernes außerhalb des Bildes. Sie können einstellen, wie sich das Filter in einem solchen Fall verhält:
        /// </summary>
        public KernelMode Mode
        {
            get { return KernelMode.NONE; }
        }

        /// <summary>
        /// Sobel Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom Sobel()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {20, 20, 20, 20, 20},
                        {17, 17, 17, 17, 17},
                        {0,  0,  0,  0,  0 },
                        {-17, -17, -17, -17, -17},
                        {-20, -20, -20, -20, -20},
                    };
            return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Left Edge Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom LeftEdge()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {-2, 1, 1},
                        {-2, 1, 1},
                        {-2, 1, 1}
                    }; return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Right Edge Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom RightEdge()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {1, 1, -2},
                        {1, 1, -2},
                        {1, 1, -2}
                    }; return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Upper Egde Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom UpperEdge()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {-2, -2, -2},
                        {1, 1, 1},
                        {1, 1, 1}
                    };
            return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Lower Edge Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom LowerEdge()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {1, 1, 1},
                        {1, 1, 1},
                        {-2, -2, -2}
                    };
            return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Lonely Pixel Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom LonelyPixel()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {-1, -1, -1},
                        {-1, 8, -1},
                        {-1, -1, -1}
                    };
            return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Lonely Holes Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom LonelyHoles()
        {
            int[,] aFilter = new int[,] 
                    {   
                        {1, 1, 1},
                        {1, -8, 1},
                        {1, 1, 1}
                    }; return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// 3x3 Matlab Style Prewitt Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom PrewittMatlab()
        {
            int[,] aFilter = new int[,]
                {
                    { 1, 1, 1}, 
                    {0, 0, 0}, 
                    {-1, -1, -1}
                }; return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// 3x3 Matlab Style Sobel Mask
        /// </summary>
        /// <returns></returns>
        public static ConvolutionMatrixCustom SobelMatlab()
        {
            int[,] aFilter = new int[,]
                {
                    { 1, 2, 1}, 
                    {0, 0, 0}, 
                    {-1, -2, -1}
                }; return new ConvolutionMatrixCustom(aFilter);
        }

        /// <summary>
        /// Gets or sets Matrix Values
        /// </summary>
        public int[,] MatrixValues
        {
            get
            {
                return this.m_aInt;
            }
            set
            {
                this.m_aInt = value;
            }
        }
    }
}